import asyncio
import threading
import time
import pymongo
from . import BinanceStrategyTool
from .BinanceStrategyTool import get_logger, get_asset_type
from .BinanceTradeAPIFactory import BinanceTradeAPIFactory

myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["binancedb"]
mydb_orders = mydb["orders"]
mydb_open_price = mydb["open_price"]


class BinanceStrategyInit(BinanceTradeAPIFactory):
    def __init__(self, UID: int, APIKey: str, SecretKey: str, symbol: str):
        logger = get_logger(str(UID) + '_Strategy_1')
        self.asset_type = get_asset_type(symbol)

        super().__init__(UID=UID, APIKey=APIKey, SecretKey=SecretKey, symbol=symbol, asset_type=self.asset_type,
                         logger=logger)

        self.long_stop_loss = 0
        self.short_stop_loss = 99999

    def _ws_openPosition(self, order):

        price = float(order.get("o").get("ap"))
        date = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(order.get('o').get('T')) / 1000))
        symbol = order.get("o").get("s")
        timeStamp = order.get('o').get('T')
        orderId = order.get("o").get("i")
        positionSide = order.get("o").get("ps")
        volume = order.get("o").get("z")

        if positionSide == "LONG":
            min_price = float(self.long_stop_loss)
            if price * 0.982 <= min_price <= price * 0.985:
                stopLoss = min_price
            else:
                stopLoss = price * 0.985
        else:
            max_price = float(self.short_stop_loss)
            if price * 1.015 <= max_price <= price * 1.018:
                stopLoss = max_price
            else:
                stopLoss = price * 1.015

        mydb_open_price.delete_many({"UID": self.UID, "positionSide": positionSide})
        mydb_open_price.insert_one({"UID": self.UID, "positionSide": positionSide, "price": float(price)})

        mydb_orders.delete_many({"UID": self.UID, "orderId": int(orderId)})
        mydb_orders.insert_one({"UID": self.UID,
                                "timeStamp": int(timeStamp),
                                "date": date,
                                "symbol": symbol,
                                "orderId": int(orderId),
                                "volume": float(volume),
                                "price": float(price),
                                "positionSide": positionSide,
                                "stopLoss": stopLoss})
        self.logger.info("该单止损价：" + str(stopLoss))

    def _hold_update(self):
        if self.all_short_quantity <= 0:
            mydb_open_price.delete_many({"UID": self.UID, "positionSide": "SHORT"})
        if self.all_long_quantity <= 0:
            mydb_open_price.delete_many({"UID": self.UID, "positionSide": "LONG"})

    def last_long_price(self):
        for var in mydb_open_price.find({"UID": self.UID, "positionSide": "LONG"}):
            return float(var.get("price"))
        return 999999

    def last_short_price(self):
        for var in mydb_open_price.find({"UID": self.UID, "positionSide": "SHORT"}):
            return float(var.get("price"))
        return 0

    def clear_orders(self):
        mydb_open_price.delete_many({"UID": self.UID})
        mydb_orders.delete_many({"UID": self.UID})

    def del_order(self, orderId):
        mydb_orders.delete_many({"UID": self.UID, "orderId": orderId})

    def get_orders(self, positionSide, sort=None):
        condition = {"UID": self.UID, "positionSide": positionSide}
        count = mydb_orders.count_documents(condition)
        if count == 0:
            return None
        if sort is not None:
            return mydb_orders.find({"UID": self.UID, "positionSide": positionSide}).sort("timeStamp", -1)[sort]
        return mydb_orders.find(condition).sort("timeStamp", -1)

    def get_all_orders(self):
        condition = {"UID": self.UID}
        count = mydb_orders.count_documents(condition)
        if count == 0:
            return None
        return mydb_orders.find(condition).sort("timeStamp", -1)

    @staticmethod
    def quantity(value, now_price):
        return value / now_price

    async def openLongStrategy(self, now_price):
        if self.lock_new_order:
            return False

        if self.all_long_quantity <= 0:  # 首次开仓
            value = self.get_asset_value(self.asset_type)
            quantity = self.quantity(value, now_price)
            await self.openLong(quantity)  # 开多

        elif now_price <= self.last_long_price() * 0.994:
            value = self.get_asset_value(self.asset_type)
            quantity = self.quantity(value, now_price)
            if self.all_long_quantity < (value / now_price) * 5:
                await self.openLong(quantity)  # 开多
            else:
                self.lock_new_order = True

        return False

    async def openShortStrategy(self, now_price):
        if self.lock_new_order:
            return False

        if self.all_short_quantity <= 0:  # 首次开仓
            value = self.get_asset_value(self.asset_type)
            quantity = self.quantity(value, now_price)
            await self.openShort(quantity)  # 开空

        elif now_price >= self.last_short_price() * 1.005:
            value = self.get_asset_value(self.asset_type)
            quantity = self.quantity(value, now_price)
            if self.all_short_quantity < (value / now_price) * 5:
                await self.openShort(quantity)  # 开空
            else:
                self.lock_new_order = True
        return False

    async def closeLongStrategy(self, now_price):
        long_orders = self.get_orders("LONG")
        if long_orders is None:
            return False

        for order in long_orders:
            if now_price >= order.get("price") * 1.003:
                if await self.closeLong(order.get("volume")):  # 平多
                    self.del_order(order.get("orderId"))
                    self.lock_new_order = False

        return False

    async def closeShortStrategy(self, now_price):
        short_orders = self.get_orders("SHORT")
        if short_orders is None:
            return False

        for order in short_orders:
            if now_price <= order.get("price") * 0.997:
                if await self.closeShort(order.get("volume")):  # 平空
                    self.del_order(order.get("orderId"))
                    self.lock_new_order = False

        return False

    async def stopLoss(self, now_price):
        orders = self.get_all_orders()
        if orders is None:
            return
        for order in orders:
            stopLoss = order.get("stopLoss")

            if stopLoss is None:
                continue

            if order.get("positionSide") == "SHORT" and float(now_price) >= float(stopLoss):
                if await self.closeShort(order.get("volume")):  # 平空
                    self.logger.info("空仓止损")
                    self.del_order(order.get("orderId"))
                    self.lock_new_order = False

            if order.get("positionSide") == "LONG" and float(now_price) <= float(stopLoss):
                if await self.closeLong(order.get("volume")):  # 平多
                    self.logger.info("多仓止损")
                    self.del_order(order.get("orderId"))
                    self.lock_new_order = False

    async def execute(self, score, now_price):
        if score <= -2:
            pass
            # await self.openLongStrategy(now_price)
        if score >= 1:
            await self.closeLongStrategy(now_price)
        if score >= 2:
            pass
            # await self.openShortStrategy(now_price)
        if score <= -1:
            await self.closeShortStrategy(now_price)

        await self.stopLoss(now_price)
        self.execute_end()

    def execute_end(self):
        pass
